﻿'Copyright (c) 2009 Grailtek

'Permission is hereby granted, free of charge, to any person
'obtaining a copy of this software and associated documentation
'files (the "Software"), to deal in the Software without
'restriction, including without limitation the rights to use,
'copy, modify, merge, publish, distribute, sublicense, and/or sell
'copies of the Software, and to permit persons to whom the
'Software is furnished to do so, subject to the following
'conditions:

'The above copyright notice and this permission notice shall be
'included in all copies or substantial portions of the Software.

'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
'EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
'OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
'NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
'HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
'WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
'FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
'OTHER DEALINGS IN THE SOFTWARE.

Imports System.Reflection
Imports System.Reflection.Emit
Imports System.Windows.Forms
Imports System.Aspect

Namespace Controls

    Public Class ObjectsPanel

        Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
            MyBase.OnLoad(e)
            Trace.Listeners.Add(New ListBoxTraceListener(tbConsole))
            tbConsole.BackColor = Drawing.Color.White
            Me.DataGridView1.AutoGenerateColumns = True
        End Sub

        Private _Assy As Assembly
        Public Property Assy() As Assembly
            Get
                Return _Assy
            End Get
            Set(ByVal value As Assembly)
                _Assy = value
                PopulateObjects()
            End Set
        End Property

        Private Sub PopulateObjects()
            Me.lbObjects.Items.Clear()
            If Assy Is Nothing Then Return
            For Each o As Item In System.ExecutorServices.GetItems(Assy, True)
                Me.lbObjects.Items.Add(o)
            Next
        End Sub

        Private Sub lbObjects_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lbObjects.SelectedIndexChanged
            Dim ao As Item = Nothing
            Dim o As Object = Me.lbObjects.SelectedItem
            If TypeOf o Is Item Then ao = DirectCast(o, Item)
            PopulateObjectsVerbs(ao)
        End Sub

        'TODO: output type scan doesn't give exactly what we want
        Private Sub PopulateObjectsVerbs(ByVal o As Item)

            Dim addverbs As New List(Of Verb)

            Me.lbObjectsVerbs.Items.Clear()
            If o Is Nothing Then Return
            Dim t As Type = o.GetType
            For Each av As Verb In System.ExecutorServices.GetVerbs(Assy, True)
                If o.DeclaringInterface.IsAssignableFrom(av.DelegateInfo.DeclaredPrimaryInterface) Then
                    Me.lbObjectsVerbs.Items.Add(av)
                    addverbs.Add(av)
                Else
                    For Each p As InputMapping In av.DelegateInfo.InputMappings
                        If p.FieldType Is o.DeclaringInterface Then
                            Me.lbObjectsVerbs.Items.Add(av)
                            Exit For
                        End If
                    Next
                End If
            Next

            'Me.tsObjectVerbs.SetVerbs(addverbs.ToArray)

        End Sub

        Private Sub btnExecute_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExecute.Click
            ExecuteVerb(SelectedVerb)
        End Sub

        Private Sub ExecuteVerb(ByVal av As Verb)
            If av Is Nothing Then Return
            Dim Data As Object = Nothing
            Try
                Data = av.Invoke(Me.ArgumentsEntry1.Arguments.Select(Of Object)(Function(a As Argument) a.Value).ToArray)
            Catch ex As TargetInvocationException
                MsgBox(Utils.GetInnerMostExceptionMessage(ex), MsgBoxStyle.Critical, av.Verb.UIName)
            End Try
            If Not av.DelegateInfo.ReturnType Is GetType(Void) Then
                If Not Data Is Nothing Then
                    If Not GetType(IEnumerable).IsAssignableFrom(Data.GetType) AndAlso Not Data.GetType.IsArray Then
                        Dim a As Array = Array.CreateInstance(Data.GetType, 1)
                        a.SetValue(Data, 0)
                        Data = a
                    End If
                End If
                Me.DataGridView1.DataSource = Data
            End If
        End Sub

        Private Sub lbObjectsVerbs_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lbObjectsVerbs.SelectedIndexChanged
            Dim av As Verb = SelectedVerb
            Me.btnExecute.Enabled = Not av Is Nothing ' AndAlso av.DelegateInfo.Parameters.Count = 0
            Me.ArgumentsEntry1.Arguments = av.DelegateInfo.GetEmptyArgs
        End Sub

        Private ReadOnly Property SelectedVerb() As Verb
            Get
                Dim ret As Verb = Nothing
                Dim o As Object = Me.lbObjectsVerbs.SelectedItem
                If TypeOf o Is Verb Then ret = DirectCast(o, Verb)
                Return ret
            End Get
        End Property

        Private Sub DataGridView1_RowEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.RowEnter
            Dim selectedItem As Object = Nothing
            If DataGridView1.SelectedRows.Count > 0 Then
                selectedItem = DataGridView1.SelectedRows(0).DataBoundItem
            End If
            If selectedItem Is Nothing Then Return
            For Each arg As Argument In Me.ArgumentsEntry1.Arguments
                If arg.Param.ParameterType.IsAssignableFrom(selectedItem.GetType) Then
                    arg.Value = selectedItem
                    Exit For
                End If
            Next
        End Sub

    End Class

End Namespace